package com.xiao.xiaorpc.loadbalancer;

import com.xiao.xiaorpc.model.ServiceMetaInfo;

import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * 一致性哈希算法
 * 使用 TreeMap 实现一致性 Hash 环，
 * 该数据结构提供了 ceilingEntry 和 firstEntry 两个方法，
 * 便于获取符合算法要求的节点。
 */
public class ConsistentHashLoadBalancer implements LoadBalancer {

    /**
     * 一致性 hash 环，存放虚拟节点
     */
    private final TreeMap<Integer, ServiceMetaInfo> virtualNodes  = new TreeMap<>();

    //虚拟节点数
    private static final int VIRTUAL_NODE_NUM = 100;

    @Override
    public ServiceMetaInfo select(Map<String, Object> requestParams, List<ServiceMetaInfo> serviceMetaInfoList) {
        if(serviceMetaInfoList == null || serviceMetaInfoList.isEmpty()){
            return null;
        }

        for (ServiceMetaInfo serviceMetaInfo : serviceMetaInfoList) {
            for(int i=0;i<VIRTUAL_NODE_NUM;i++){
                int hashCode = getHash(serviceMetaInfo.getServiceAddress() + "#" + i);
                virtualNodes.put(hashCode, serviceMetaInfo);
            }
        }
        // 获取调用请求的 hash 值
        int hash = getHash(requestParams);

        //选择最接近且大于等于调用请求 hash 值的虚拟节点
        Map.Entry<Integer, ServiceMetaInfo> entry = virtualNodes.ceilingEntry(hash);
        if(entry == null){
            // 如果没有大于等于调用请求 hash 值的虚拟节点，则返回环首部的节点
            entry = virtualNodes.firstEntry();
        }

        return entry.getValue();
    }

    /**
     * Hash 算法，可自行实现
     *
     * @param key
     * @return
     */
    private int getHash(Object key) {
        return key.hashCode();
    }
}
